
CMSForm = Class.extend('ChangeTracker').extend('Observable');
CMSForm.prototype = {
	initialize : function(fn) {
		this.ChangeTracker.initialize();
		this.formName = fn;
		this.prepareForm();
	},
	
	/**
	 * Trigger normal save event, helpful e.g. when enter key is pressed in
	 * single line input fields.
	 */
	onsubmit: function(e) {
		this.save();
		
		Event.stop(e);
		return false;
	},
	
	/**
	 * Processing called whenever a page is loaded in the right - including the initial one
	 */
	prepareForm : function() {
		ajaxActionsAtTop(this.id, 'form_actions_' + this.formName, this.formName);
		
		// Update the nav items down the bottom
		if($('SwitchView') && $('AjaxSwitchView')) {
			$('SwitchView').innerHTML = $('AjaxSwitchView').innerHTML;
			$('AjaxSwitchView').innerHTML = '';
			Behaviour.apply('SwitchView'); // This is needed so calendar still works
		}
	},
	
	/**
	 * Load actions from a string containing the HTML content
	 */
	loadActionsFromString : function(actionHTML) {
		var actionHolder = $('form_actions_' + this.formName);
		actionHolder.innerHTML = actionHTML;
		prepareAjaxActions(actionHolder, this.id, this.formName);
	},

	/**
	 * Close the form down without any corrective action, after its been deleted.
	 */
	closeIfSetTo: function(id) {
		if(this.elements.ID && this.elements.ID.value == id) {
    		// Note: TinyMCE coupling
			tinymce_removeAll();
			this.innerHTML = "<p>" + ss.i18n._t('LeftAndMain.PAGEWASDELETED') + "</p>";
		}			
	},

	/**
	 * Reload lose the form if the current page is open.
	 */
	reloadIfSetTo: function(id) {
		if(this.elements.ID && this.elements.ID.value == id) {
			this.getPageFromServer(id);
		}			
	},
	
	close: function() {
		this.innerHTML = "<p>&#160;</p>";
		var actions;
		if(actions = $('form_actions_' + this.formName)) {
			actions.parentNode.removeChild(actions);
		}
	},
	
	updateStatus: function( newStatus ) {
		
		if( $('Form_EditForm_Status') )
			$('Form_EditForm_Status').innerHTML = "STATUS: " + newStatus;
	},

	/**
	 * Load a new page into the right-hand form.
	 * 
	 * @param formContent string
	 * @param response object (optional)
	 * @param evalResponse boolean (optional)
	 */
	loadNewPage : function(formContent, response, evalResponse) {
		var rightHTML = formContent;
		
		// reset the version view history 
		if($('versions_holder')) $('versions_holder').reset();
		
		// Rewrite # links
		rightHTML = rightHTML.replace(/(<a[^>]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#');
		
		// Rewrite iframe links (for IE)
		rightHTML = rightHTML.replace(/(<iframe[^>]*src=")([^"]+)("[^>]*>)/g, '$1' + baseHref() + '$2$3');

		// Note: TinyMCE coupling
		tinymce_removeAll();

		// Prepare iframes for removal, otherwise we get loading bugs
		var i, allIframes = this.getElementsByTagName('iframe');
		if(allIframes) for(i=0;i<allIframes.length;i++) {
			allIframes[i].contentWindow.location.href = 'about:blank';
			allIframes[i].parentNode.removeChild(allIframes[i]);
		}

		if(response && evalResponse) {
			// no-op, has already been evaluated by prototype.js
		} else {
			this.innerHTML = rightHTML;
		}
		
		// Get the form attributes from embedded fields
		var attr;
		
		for(attr in {'action':true  ,'method':true,'enctype':true,'name':true}) {
			if(this.elements['_form_' + attr]) {
				this[attr] = this.elements['_form_' + attr].value;
				this.elements['_form_' + attr].parentNode.removeChild(this.elements['_form_' + attr]);
			}
		}
		
		allIframes = this.getElementsByTagName('iframe');
		if(allIframes) for(i=0;i<allIframes.length;i++) {
			try {
				allIframes[i].contentWindow.location.href = allIframes[i].src;
			} catch(er) { alert('Error in LeftAndMain_right.js CMSForm.loadNewPage: ' + er.message); }
		}
		
		_TAB_DIVS_ON_PAGE = [];

		//initTabstripe() become livequery in tabstrip.js, so we don't need to call it for each tab strip here.

		
		// We assume that an evaluated response is generated by FormResponse
		// which takes care of calling these method it
		if (!evalResponse) {
			if (this.prepareForm) this.prepareForm();
			Behaviour.apply(this);
		}

		if(this.resetElements) this.resetElements();
		
		window.ontabschanged();

		// If there's a title field and it's got a "new XX" value, focus/select that first
		// This is really a little too CMS-specific (as opposed to LeftAndMain), but the cleanup can happen after jQuery refactoring
		if($('input#Form_EditForm_Title') && $('input#Form_EditForm_Title').value.match(/^new/i)) {
    		$('input#Form_EditForm_Title').select();
		}
	},
	/**
	 * Save the contens of the form, by submitting it and resetting is changed checker
	 * on success.
	 *
         * @param ifChanged boolean     if true, only save changed fields
         * @param callAfter function (optional) callback function to run after the AJAX request.
         * @param action string   (optional, default is 'save') action to call via AJAX.
	 * @param publish boolean (optional) whether to publish in addition to saving
	 */
	save: function(ifChanged, callAfter, action, publish) {
		_AJAX_LOADING = true;
		// Note: TinyMCE coupling
		if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
		if(!action) action = "save";

		var __callAfter = callAfter;
		var __form = this;
		
		if(__form.notify && __form.elements.ID != undefined) __form.notify('BeforeSave', __form.elements.ID.value);

		// validate if required
		if(this.validate && !this.validate()) {
			// TODO Automatically switch to the tab/position of the first error
			statusMessage("Validation failed.", "bad");
			
			if($('Form_EditForm_action_save') && $('Form_EditForm_action_save').stopLoading) $('Form_EditForm_action_save').stopLoading();
			
			return false;
		}
		
		var success = function(response) {
			__form.resetElements();
			if(__callAfter) __callAfter();
			if(__form.notify && __form.elements.ID != undefined) __form.notify('PageSaved', __form.elements.ID.value);
			if($('Form_EditForm_action_save') && $('Form_EditForm_action_save').stopLoading) $('Form_EditForm_action_save').stopLoading();
			_AJAX_LOADING = false;
		}
		
		if(ifChanged) {
			var data = this.serializeChangedFields('ID') + '&ajax=1&action_' + action + '=1';
		} else {
			var data = this.serializeAllFields() + '&ajax=1&action_' + action + '=1';
		}
		if(publish)
		{
			data += '&publish=1';
		}
		
		statusMessage(ss.i18n._t('CMSMAIN.SAVING'), null, true);

		new Ajax.Request(this.action, {
			method : this.method,
			postBody: data,
			onSuccess : success,
			onFailure : function(response) {
				var msg;
				// Only show plain responses, and trim them to avoid long stack traces
				if(response.getResponseHeader('Content-Type', 'text/plain')) {
					msg = response.responseText;
				} else {
					msg = 'Error saving content';
				}
				if(msg.length > 300) msg = longMsg.substr(0,300) + '...';
				errorMessage(msg);
				if($('Form_EditForm_action_save') && $('Form_EditForm_action_save').stopLoading) $('Form_EditForm_action_save').stopLoading();
				_AJAX_LOADING = false;
			}
		});
	},
	
	loadPage_url : 'admin/getpage'
}

CMSRightForm = Class.extend('CMSForm');
CMSRightForm.prototype = {
	intialize: function() {
		this.CMSForm.initialize('right');
	},


	/**
	 * Load the given URL (with &ajax=1) into this form
	 */
	loadURLFromServer : function(url) {
		var urlParts = url.match( /ID=(\d+)/ );
		var id = urlParts ? urlParts[1] : null;
		
		if( !url.match( /^https?:\/\/.*/ ) )
			url = document.getElementsByTagName('base')[0].href + url;
		
		new Ajax.Request( url + '&ajax=1', {
			asynchronous : true,
			onSuccess : function( response ) {
				$('Form_EditForm').successfullyReceivedPage(response,id);
			},
			onFailure : function(response) { 
				alert(response.responseText);
				errorMessage('error loading page',response);
			}
		});
	},
	
	successfullyReceivedPage : function(response,pageID) {
		var loadingNode = $('sitetree').loadingNode;
		
		if( loadingNode && pageID && parseInt( $('sitetree').getIdxOf( loadingNode ) ) != pageID ) {
			return;
		}
			
		// must wait until the javascript has finished
		document.body.style.cursor = 'wait';
	
		this.loadNewPage(response.responseText);
		
		var subform;
		if(subform = $('Form_SubForm')) subform.close();
		
		if(this.elements.ID) {
			this.notify('PageLoaded', this.elements.ID.value);
		}
		
		if(this.receivingID) {			
			// Treenode might not exist if that part of the tree is closed
			var treeNode = loadingNode ? loadingNode : $('sitetree').getTreeNodeByIdx(this.receivingID);
			if(treeNode) {
				$('sitetree').setCurrentByIdx(treeNode.getIdx());
				treeNode.removeNodeClass('loading');
			}
			statusMessage('');
		}
		
		// must wait until the javascript has finished
		document.body.style.cursor = 'default';
		
	},
	didntReceivePage : function(response) {
		errorMessage('error loading page', response); 
		$('sitetree').getTreeNodeByIdx(this.elements.ID.value).removeNodeClass('loading');
	},
			
	
	/**
	 * Request a page from the server via Ajax
	 */
	getPageFromServer : function(id, treeNode) {
		// if(id && id.match(/^[A-Za-z0-9_]+$/)) {
		if(id && (id == 'root' || parseInt(id) == id || (id.substr && id.substr(0,3) == 'new') )) {
			this.receivingID = id;

			// Treenode might not exist if that part of the tree is closed
			if(!treeNode) treeNode = $('sitetree').getTreeNodeByIdx(id);
			
			if(treeNode) {
				$('sitetree').loadingNode = treeNode;
				treeNode.addNodeClass('loading');
				url = treeNode.aTag.href + (treeNode.aTag.href.indexOf('?')==-1?'?':'&') + 'ajax=1';
			}
			if(SiteTreeHandlers.loadPage_url) {
				var sep = (SiteTreeHandlers.loadPage_url.indexOf('?') == -1) ? '?' : '&';
				url = SiteTreeHandlers.loadPage_url + sep + 'ID=' + id;
			}
			
			// used to set language in CMSMain->init()
			var lang = $('LangSelector') ? $F('LangSelector') : null;
			if(lang) {
			  url += '&locale='+lang;
			}

			statusMessage(ss.i18n._t('LOADING', 'loading...')); 
			this.loadURLFromServer(url);
		} else {
			throw("getPageFromServer: Bad page ID: " + id);
		}
	}
	
	/**
	 * Set the status field
	 */
	/*setStatus: function(newStatus) {
		var statusLabel = document.getElementsBySelector('label.pageStatusMessage')[0];
		if(statusLabel) statusLabel.innerHTML = "STATUS: " + newStatus;		
	}*/
}

CMSForm.applyTo('#Form_SubForm');
CMSRightForm.applyTo('#Form_EditForm', 'right');

function action_save_right() {
	_AJAX_LOADING = true;

	// Don't need to restore the button state after ajax success because the form is replaced completely
	var btn = jQuery('#Form_EditForm_action_save');
	btn.val(ss.i18n._t('CMSMAIN.SAVING')).addClass('loading').attr('disabled', 'disabled');
	btn[0].stopLoading = function() {
		btn.val('Save').removeClass('loading').removeAttr('disabled');
	};
	
	$('Form_EditForm').save(false);
}

function action_save_siteconfig_right() {
	_AJAX_LOADING = true;
	if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();
	$('Form_EditForm_action_save_siteconfig').value = ss.i18n._t('CMSMAIN.SAVING');
	$('Form_EditForm_action_save_siteconfig').className = 'action loading';

	$('Form_EditForm').save(null, function() {
		if($('Form_EditForm_action_save_siteconfig') && $('Form_EditForm_action_save_siteconfig').className.indexOf('loading') != -1) {
			$('Form_EditForm_action_save_siteconfig').value = 'Save';
			Element.removeClassName($('Form_EditForm_action_save_siteconfig'), 'loading');
		}
	}, 'save_siteconfig');
}

/**
 * Handle auto-saving.  Detects if changes have been made, and if so save everything on the page.
 * If confirmation is true it will ask for confirmation.
 */
function autoSave(confirmation, callAfter) {
	// Note: TinyMCE coupling
	if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();

	var __forms = []
	if($('Form_EditForm')) __forms.push($('Form_EditForm'));
	if($('Form_SubForm')) __forms.push($('Form_SubForm'));
	
	var __somethingHasChanged = false;
	var __callAfter = callAfter;
	
	__forms.each(function(form) {
		if(form.isChanged && form.isChanged()) {
			__somethingHasChanged = true;
		}
	});
	
	if(__somethingHasChanged) {
		// Note: discard and cancel options are no longer used since switching to confirm dialog.
		// 	save is still used if confirmation = false
		var options = {
			save: function() {
				statusMessage(ss.i18n._t('CMSMAIN.SAVING'), '', true);
				var i;
				for(i=0;i<__forms.length;i++) {
					if(__forms[i].isChanged && __forms[i].isChanged()) {
						if(i == 0) __forms[i].save(true, __callAfter);
						else __forms[i].save(true);
					}
				}
			},
			discard: function() {
				__forms.each(function(form) { form.resetElements(false); });
				if(__callAfter) __callAfter();
			},
			cancel: function() {
			}
		}
		
		if(confirmation ) {
			if(confirm(ss.i18n._t('LeftAndMain.CONFIRMUNSAVED'))) 
			{
				// OK was pressed, call function for what was clicked on
				if(__callAfter) __callAfter();
			} else {
				// Cancel was pressed, stay on the current page
				return false;
			}
		} else {
			options.save();
		}

	} else {
		if(__callAfter) __callAfter();
	}
}

window.name = windowName('cms');

/**
 * Return a unique window name that contains the URL
 */
function windowName(suffix) {
	var base = document.getElementsByTagName('base')[0].href.replace('~','').replace('http://','').replace(/\//g,'_').replace(/\./g,'_');
	return base + suffix;
}

/**
 * Remove all the currently active TinyMCE editors.
 * Note: everything that calls this has an inappropriate coupling to TinyMCE.
 * Perhaps an observer pattern could be used, where TinyMCE listens to a onBeforeCMSPageLoad
 * event?
 */
function tinymce_removeAll() {
	if((typeof tinymce != 'undefined') && tinymce.EditorManager) {
		var id;
		for(id in tinymce.EditorManager.editors) {
			tinymce.EditorManager.editors[id].remove();
		}
		tinymce.EditorManager.editors = {};
	}
		
}
